#include "thread.hpp"
#include "lockGuard.hpp"
#include <queue>
#include <vector>
#include "Task.hpp"

#define THREADNUM 5 // 线程数量

template <class T>
class ThreadPool
{
public:
    ThreadPool(int num = THREADNUM)
        : _num(num)
    {
        pthread_mutex_init(&_mtx, nullptr); // 初始化互斥锁
        pthread_cond_init(&_cond, nullptr); // 初始化条件变量

        for (int i = 0; i < _num; ++i)
        {
            _threads.push_back(new Thread(i, routine, this));
        }
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mtx); // 释放互斥锁
        pthread_cond_destroy(&_cond); // 释放条件变量

        for(auto& td : _threads)
        {
            td->join();
            delete td;
        }
    }

    void run() // 运行线程池
    {
        for(auto& td : _threads)
        {
            td->start();
        }
    }

    static void *routine(void *args) // 线程执行函数
    {
        ThreadDate *td = (ThreadDate *)args;
        ThreadPool<T> *tp = (ThreadPool<T> *)td->_args;

        while (true)
        {
            T task;
            {
                lockGuard lock(&tp->_mtx); // 上锁
                while (tp->_taskQueue.empty())
                {
                    pthread_cond_wait(&tp->_cond, &tp->_mtx); // 获取条件变量
                }
                // 获取任务
                task = tp->_taskQueue.front();
                tp->_taskQueue.pop();
            }
            // 执行任务
            std::cout << td->_name << "->" << std::endl;
            task();
        }

        return nullptr;
    }

    void push(const T& task) // 插入任务
    {
        lockGuard lock(&_mtx); // 申请互斥锁
        _taskQueue.push(task); // 插入任务
        pthread_cond_signal(&_cond);  // 唤醒线程
    }

private:
    int _num;                     // 线程数量
    std::queue<T> _taskQueue;     // 任务队列
    std::vector<Thread*> _threads; // 线程
    pthread_mutex_t _mtx;         // 任务队列互斥锁
    pthread_cond_t _cond;         // 线程池条件变量
};